﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Percolation.Gui
{
    [Serializable]
    public sealed class CommonSettings
    {
        public int NetWidth { get; set; }
        public int NetHeight { get; set; }
        public int PackCount { get; set; }

        public CommonSettings(int netWidth, int netHeight, int packCount)
        {
            NetWidth = netWidth;
            NetHeight = netHeight;
            PackCount = packCount;
        }

        public CommonSettings(): this(50, 50, 0)
        {
        }
    }

    [Serializable]
    public sealed class NetPackSettings
    {
        public NetTypeEnum NetType { get; set; }

        public int Count 
        {
            get
            {
                if (NetType == NetTypeEnum.Random || NetType == NetTypeEnum.Gradient)
                    return m_count;
                else
                    throw new ApplicationException("Internal error");
            }

            set
            {
                if (NetType == NetTypeEnum.Random || NetType == NetTypeEnum.Gradient)
                    m_count = value;
                else
                    throw new ApplicationException("Internal error");
            }
        }

        public double Probability0
        {
            get
            {
                if (NetType == NetTypeEnum.Random || NetType == NetTypeEnum.Gradient)
                    return m_probability0;
                else
                    throw new ApplicationException("Internal error");
            }

            set
            {
                if (NetType == NetTypeEnum.Random || NetType == NetTypeEnum.Gradient)
                    m_probability0 = value;
                else
                    throw new ApplicationException("Internal error");
            }
        }        
        public double Probability1
        {
            get
            {
                if (NetType == NetTypeEnum.Gradient)
                    return m_probability1;
                else
                    throw new ApplicationException("Internal error");
            }

            set
            {
                if (NetType == NetTypeEnum.Gradient)
                    m_probability1 = value;
                else
                    throw new ApplicationException("Internal error");
            }
        }
        public NetPackSettings(NetTypeEnum netType)
        {
            NetType = netType;
        }

        public NetParams getNetParams(int width, int height)
        {
            if (NetType == NetTypeEnum.Random)
                return new RandomNetParams(width, height, Probability0);
            else if (NetType == NetTypeEnum.Gradient)
                return null;
            else
                return new NetParams(NetType, width, height);
        }

        public override string ToString()
        {
            String result = EnumUtils.GetString(NetType);
            if (NetType == NetTypeEnum.Gradient)
                result += " (" + Count + " exp.), [" + Probability0 + "-" + Probability1 + "]";
            else if (NetType == NetTypeEnum.Random)
                result += " (" + Count + " exp.), [" + Probability0 + "]";

            return result;
        }

        private int m_count = 0;
        private double m_probability0 = 0.0;
        private double m_probability1 = 0.0;
    }

    [Serializable]
    public sealed class PacksSettings
    {
        public PacksSettings()
        {
        }

        public PacksSettings(PacksSettings instance)
        {
            m_packs = new List<NetPackSettings>(instance.m_packs);
        }

        public void Copy(PacksSettings instance)
        {
            m_packs = new List<NetPackSettings>(instance.m_packs);
        }

        public int packCount()
        {
            return m_packs.Count;
        }

        public void addPack(NetPackSettings pack)
        {
            m_packs.Add(pack);
        }

        public void removePack(int n)
        {
            m_packs.RemoveAt(n);
        }

        public NetPackSettings getPack(int n)
        {
            if (n < 0 || n >= m_packs.Count)
                return null; 

            return m_packs[n];
        }

        protected List<NetPackSettings> m_packs = new List<NetPackSettings>();
    }

    [Serializable]
    public sealed class AlgorithmsSettings
    {
        public System.Drawing.Color BoltRouteColor { get; set; }
        public System.Drawing.Color BoltAddedCellColor { get; set; }
        public EdgeWeightSettings BoltSettings { get; set; }

        public AlgorithmsSettings()
        {
            BoltSettings = new EdgeWeightSettings();
        }

        public void Copy(AlgorithmsSettings instance)
        {
            BoltRouteColor = instance.BoltRouteColor;
            BoltAddedCellColor = instance.BoltAddedCellColor;
            BoltSettings = instance.BoltSettings;
        }
    }

    [Serializable]
    public sealed class ProgramSettings
    {
        public static ProgramSettings Instance
        {
            get
            {
                if (m_instance == null)
                    m_instance = new ProgramSettings();

                return m_instance;
            }
        }

        public CommonSettings getCommon()
        {
            return m_common;
        }

        public PacksSettings getPack()
        {
            return m_packs;
        }

        public AlgorithmsSettings getAlgorithms()
        {
            return m_algorithms;
        }

        protected CommonSettings m_common = new CommonSettings();
        protected PacksSettings m_packs = new PacksSettings();
        protected AlgorithmsSettings m_algorithms = new AlgorithmsSettings();

        private static ProgramSettings m_instance;
        
        private ProgramSettings() 
        {
        }
    }
}
